﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;

namespace ajayumi.Platform.Win.CircularProgress
{
    public partial class SpinningProgress : System.Windows.Forms.UserControl
    {
        private Color m_InactiveColour = Color.FromArgb(218, 218, 218);
        private Color m_ActiveColour = Color.FromArgb(35, 146, 33);
        private Color m_TransistionColour = Color.FromArgb(129, 242, 121);

        private Region innerBackgroundRegion;
        private System.Drawing.Drawing2D.GraphicsPath[] segmentPaths = new System.Drawing.Drawing2D.GraphicsPath[12];

        private bool m_AutoIncrement = true;
        private double m_IncrementFrequency = 100;
        private bool m_BehindIsActive = true;
        private int m_TransitionSegment = 0;

        private System.Timers.Timer m_AutoRotateTimer;
        [System.ComponentModel.DefaultValue(typeof(Color), "218, 218, 218")]
        public Color InactiveSegmentColour
        {
            get
            {
                return m_InactiveColour;
            }
            set
            {
                m_InactiveColour = value;
                Invalidate();
            }
        }
        [System.ComponentModel.DefaultValue(typeof(Color), "35, 146, 33")]
        public Color ActiveSegmentColour
        {
            get
            {
                return m_ActiveColour;
            }
            set
            {
                m_ActiveColour = value;
                Invalidate();
            }
        }
        [System.ComponentModel.DefaultValue(typeof(Color), "129, 242, 121")]
        public Color TransistionSegmentColour
        {
            get
            {
                return m_TransistionColour;
            }
            set
            {
                m_TransistionColour = value;
                Invalidate();
            }
        }
        [System.ComponentModel.DefaultValue(true)]
        public bool BehindTransistionSegmentIsActive
        {
            get
            {
                return m_BehindIsActive;
            }
            set
            {
                m_BehindIsActive = value;
                Invalidate();
            }
        }
        [System.ComponentModel.DefaultValue(-1)]
        public int TransistionSegment
        {
            get
            {
                return m_TransitionSegment;
            }
            set
            {
                if (value > 11 || value < -1)
                {
                    throw new ArgumentException("TransistionSegment must be between -1 and 11");
                }
                m_TransitionSegment = value;
                Invalidate();
            }
        }
        [System.ComponentModel.DefaultValue(true)]
        public bool AutoIncrement
        {
            get
            {
                return m_AutoIncrement;
            }
            set
            {
                m_AutoIncrement = value;

                if (value == false && m_AutoRotateTimer != null)
                {
                    m_AutoRotateTimer.Dispose();
                    m_AutoRotateTimer = null;
                }

                if (value == true && m_AutoRotateTimer == null)
                {
                    m_AutoRotateTimer = new System.Timers.Timer(m_IncrementFrequency);
                    m_AutoRotateTimer.Elapsed += new System.Timers.ElapsedEventHandler(IncrementTransisionSegment);
                    m_AutoRotateTimer.Start();
                }
            }
        }
        [System.ComponentModel.DefaultValue(100)]
        public double AutoIncrementFrequency
        {
            get
            {
                return m_IncrementFrequency;
            }
            set
            {
                m_IncrementFrequency = value;

                if (m_AutoRotateTimer != null)
                {
                    AutoIncrement = false;
                    AutoIncrement = true;
                }
            }
        }

        public SpinningProgress()
        {
            //  This call is required by the Windows Form Designer.
            InitializeComponent();

            //  Add any initialization after the InitializeComponent() call.
            CalculateSegments();

            m_AutoRotateTimer = new System.Timers.Timer(m_IncrementFrequency);
            m_AutoRotateTimer.Elapsed += new System.Timers.ElapsedEventHandler(IncrementTransisionSegment);
            this.DoubleBuffered = true;
            m_AutoRotateTimer.Start();

            this.EnabledChanged += new EventHandler(SpinningProgress_EnabledChanged);
            // events handled by ProgressDisk_Paint
            this.Paint += new PaintEventHandler(ProgressDisk_Paint);
            // events handled by ProgressDisk_Resize
            this.Resize += new EventHandler(ProgressDisk_Resize);
            // events handled by ProgressDisk_SizeChanged
            this.SizeChanged += new EventHandler(ProgressDisk_SizeChanged);
        }

        private void IncrementTransisionSegment(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (m_TransitionSegment == 11)
            {
                m_TransitionSegment = 0;
                m_BehindIsActive = !(m_BehindIsActive);
            }
            else if (m_TransitionSegment == -1)
            {
                m_TransitionSegment = 0;
            }
            else
            {
                m_TransitionSegment += 1;
            }

            Invalidate();
        }


        private void CalculateSegments()
        {
            //Rectangle rctFull = new Rectangle(0, 0, this.Width , this.Height );
            //Rectangle rctInner = new Rectangle(((this.Width * 7) / 30),
            //                                    ((this.Height * 7) / 30),
            //                                    (this.Width - ((this.Width * 14) / 30)),
            //                                    (this.Height - ((this.Height * 14) / 30)));

            //修改使其居中，并留出空余绘制边框
            Rectangle rctFull = new Rectangle(1, 1, this.Width - 3, this.Height - 3);
            Rectangle rctInner = new Rectangle(((this.Width * 8) / 30),
                                                ((this.Height * 8) / 30),
                                                (this.Width - ((this.Width * 16) / 30)),
                                                (this.Height - ((this.Height * 16) / 30)));

            System.Drawing.Drawing2D.GraphicsPath pthInnerBackground = null;

            // Create 12 segment pieces
            for (int intCount = 0; intCount < 12; intCount++)
            {
                segmentPaths[intCount] = new System.Drawing.Drawing2D.GraphicsPath();

                // We subtract 90 so that the starting segment is at 12 o'clock
                segmentPaths[intCount].AddPie(rctFull, (intCount * 30) - 90, 25);
            }

            // Create the center circle cut-out
            pthInnerBackground = new System.Drawing.Drawing2D.GraphicsPath();
            pthInnerBackground.AddPie(rctInner, 0, 360);
            innerBackgroundRegion = new Region(pthInnerBackground);
        }


        private void SpinningProgress_EnabledChanged(object sender, System.EventArgs e)
        {
            if (Enabled == true)
            {
                if (m_AutoRotateTimer != null)
                {
                    m_AutoRotateTimer.Start();
                }
            }
            else
            {
                if (m_AutoRotateTimer != null)
                {
                    m_AutoRotateTimer.Stop();
                }
            }
        }


        private void ProgressDisk_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            e.Graphics.ExcludeClip(innerBackgroundRegion);

            for (int intCount = 0; intCount < 12; intCount++)
            {
                if (this.Enabled)
                {
                    if (intCount == m_TransitionSegment)
                    {
                        // If this segment is the transistion segment, colour it differently
                        e.Graphics.FillPath(new SolidBrush(m_TransistionColour), segmentPaths[intCount]);
                    }
                    else if (intCount < m_TransitionSegment)
                    {
                        // This segment is behind the transistion segment
                        if (m_BehindIsActive)
                        {
                            // If behind the transistion should be active, 
                            // colour it with the active colour
                            e.Graphics.FillPath(new SolidBrush(m_ActiveColour), segmentPaths[intCount]);
                        }
                        else
                        {
                            // If behind the transistion should be in-active, 
                            // colour it with the in-active colour
                            e.Graphics.FillPath(new SolidBrush(m_InactiveColour), segmentPaths[intCount]);
                        }
                    }
                    else
                    {
                        // This segment is ahead of the transistion segment
                        if (m_BehindIsActive)
                        {
                            // If behind the the transistion should be active, 
                            // colour it with the in-active colour
                            e.Graphics.FillPath(new SolidBrush(m_InactiveColour), segmentPaths[intCount]);
                        }
                        else
                        {
                            // If behind the the transistion should be in-active, 
                            // colour it with the active colour
                            e.Graphics.FillPath(new SolidBrush(m_ActiveColour), segmentPaths[intCount]);
                        }
                    }
                }
                else
                {
                    // Draw all segments in in-active colour if not enabled
                    e.Graphics.FillPath(new SolidBrush(m_InactiveColour), segmentPaths[intCount]);
                }
            }

            //绘制边框
            e.Graphics.DrawRectangle(new Pen(Color.Black, 1f), 0, 0, this.Width - 1, this.Height - 1);
        }


        private void ProgressDisk_Resize(object sender, System.EventArgs e)
        {
            CalculateSegments();
        }


        private void ProgressDisk_SizeChanged(object sender, System.EventArgs e)
        {
            CalculateSegments();
        }

    }
}
